#include <iostream>

using namespace std;
const int N = 1e6 + 10;
#define lc p << 1
#define rc p << 1 | 1
using ll = long long;
struct node
{
    int l, r;
    ll max, add, update;
    bool st;
} tr[N << 2];
int n, q;
int a[N];

void pushUp(int p)
{
    tr[p].max = max(tr[lc].max, tr[rc].max);
}
void bulid(int p, int l, int r)
{
    tr[p] = {l, r, a[l], 0, 0, 0};
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    bulid(lc, l, mid), bulid(rc, mid + 1, r);
    pushUp(p);
}
void lazy(int p, bool flag, ll update, ll add)
{
    if (flag)
    {
        tr[p].max = update;
        tr[p].add = 0;
        tr[p].update = update;
        tr[p].st = flag;
    }
    else{
        tr[p].max += add;
        tr[p].add += add;
    }
}

void pushDown(int p)
{
    lazy(lc, tr[p].st, tr[p].update, tr[p].add);
    lazy(rc, tr[p].st, tr[p].update, tr[p].add);

    tr[p].add = 0, tr[p].st = 0, tr[p].update = 0;
}
void modify(bool flag, int p, int x, int y, ll update, ll add)
{
    int l = tr[p].l, r = tr[p].r;
    if (x <= l && r <= y)
    {
        lazy(p, flag, update, add);
        return ;
    }

    int mid = (l + r) >> 1;
    pushDown(p);
    if (x <= mid) modify(flag, lc, x, y, update, add);
    if (y > mid) modify(flag, rc, x, y, update, add);
    pushUp(p);
}
ll query(int p, int x, int y)
{
    int l = tr[p].l, r = tr[p].r;
    if (x <= l && r <= y) return tr[p].max;

    pushDown(p);
    int mid = (l + r) >> 1;
    ll ret = -1e18;
    if (x <= mid) ret = max(ret, query(lc, x, y));
    if (y > mid) ret = max(ret, query(rc, x, y));

    return ret;
}
int main()
{
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    bulid(1, 1, n);
    while (q--)
    {
        int op;
        scanf("%d", &op);
        int l, r;
        int x;
        scanf("%d%d", &l, &r);
        if (op == 1)
        {
            scanf("%d", &x);
            // cin >> l >> r >> x;
            modify(true, 1, l, r, x, 0);
        }
        else if (op == 2)
        {
            scanf("%d", &x);
            modify(false, 1, l, r, 0, x);
        }
        else
            printf("%lld\n", query(1, l, r));
    }
    return 0;
}